package com.wgchao.amc.service.impl;

import com.wgchao.amc.common.AuthoMenuInfo;
import com.wgchao.amc.common.EvaluateInfo;
import com.wgchao.amc.common.ResultCommon;
import com.wgchao.amc.entity.autho.*;
import com.wgchao.amc.entity.base.*;
import com.wgchao.amc.entity.menu.SysMenuProject;
import com.wgchao.amc.mapstruct.dto.SysBaseFuncDTO;
import com.wgchao.amc.mapstruct.mapper.SysBaseFuncMapper;
import com.wgchao.amc.mapstruct.mapper.expand.SysBaseMenuMapperExpand;
import com.wgchao.amc.repository.autho.*;
import com.wgchao.amc.repository.base.*;
import com.wgchao.amc.repository.menu.SysMenuProjectRepository;
import com.wgchao.amc.service.AuthoService;
import com.wgchao.amc.service.EvaluateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName: AuthoServiceImpl
 * @author: wgchao
 * @createTime: 2019/10/31 3:24 PM
 * @Description: TODO
 */
@Service
@Transactional
public class AuthoServiceImpl implements AuthoService, EvaluateService {
    @Autowired
    private SysBaseUserRepository userRepository;
    @Autowired
    private SysMenuProjectRepository projectRepository;
    @Autowired
    private SysAuthoUserRepository authoUserRepository;
    @Autowired
    private SysBaseMenuRepository menuRepository;
    @Autowired
    private SysBaseMenuMapperExpand menuMapperExpand;
    @Autowired
    private SysAuthoUserFuncRepository authoUserFuncRepository;
    @Autowired
    private SysBaseFuncRepository funcRepository;
    @Autowired
    private SysBaseFuncMapper funcMapper;
    @Autowired
    private SysAuthoGroupRepository authoGroupRepository;
    @Autowired
    private SysBaseUgRepository ugRepository;
    @Autowired
    private SysBaseUrRepository urRepository;
    @Autowired
    private SysAuthoRoleRepository authoRoleRepository;
    @Autowired
    private SysAuthoGroupFuncRepository authoGroupFuncRepository;
    @Autowired
    private SysAuthoRoleFuncRepository authoRoleFuncRepository;


    /**
     * 查询用户菜单权限
     * @param userId 用户ID
     * @param proMark 项目标示
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<List<AuthoMenuInfo>> searchMenusOfUser(Long userId, String proMark) throws Exception {
        EvaluateInfo evaluateInfo = evaluate(userId, uId -> {
            Long userid = Long.valueOf(uId.toString());
            Optional<SysBaseUser> userOptional = userRepository.findById(userid);
            if(!userOptional.isPresent()){
                return new EvaluateInfo(false, "用户不存在");
            }
            SysBaseUser user = userOptional.get();
            if(user.isCancel()){
                return new EvaluateInfo(false, "用户已注销");
            }
            if(user.isDel()){
                return new EvaluateInfo(false, "用户已删除");
            }
            SysMenuProject project = projectRepository.findFirstByProMark(proMark);
            if(project == null){
                return new EvaluateInfo(false, "项目不存在");
            }
            return new EvaluateInfo(true, null);
        });

        List<AuthoMenuInfo> authoMenuInfoList = new ArrayList<>();

        //获取用户菜单权限
        List<AuthoMenuInfo> user_authoMenuInfos = getUserAuthoMenus(userId, proMark);
        if(user_authoMenuInfos != null){
            authoMenuInfoList.addAll(user_authoMenuInfos);
        }


        //获取用户所在部门的权限
        List<AuthoMenuInfo> group_authoMenuInfos = getGroupAuthoMenus(userId, proMark);
        if(group_authoMenuInfos != null){
            authoMenuInfoList.addAll(group_authoMenuInfos);
        }


        //获取用户所属角色的权限
        List<AuthoMenuInfo> role_authoMenuInfos = getRoleAuthoMenus(userId, proMark);
        if(role_authoMenuInfos != null){
            authoMenuInfoList.addAll(role_authoMenuInfos);
        }

        return ResultCommon.success().setData(authoMenuInfoList);
    }

    /**
     * 获取用户菜单权限
     * @param userId
     * @param proMark
     * @return
     */
    private List<AuthoMenuInfo> getUserAuthoMenus(Long userId, String proMark){
        List<SysAuthoUser> authoUserList = authoUserRepository.findAllByUserIdAndProMarkOrderById(userId, proMark);
        if(authoUserList!=null && !authoUserList.isEmpty()){
            List<AuthoMenuInfo> authoMenuInfos = authoUserList.stream().map(sysAuthoUser -> {
                Optional<SysBaseMenu> menuOptional = menuRepository.findById(sysAuthoUser.getMenuId());
                AuthoMenuInfo authoMenuInfo = new AuthoMenuInfo();
                if(menuOptional.isPresent()){
                    SysBaseMenu menu = menuOptional.get();
                    authoMenuInfo.setMenuInfo(menuMapperExpand.toDTO(menu));
                }
                List<SysAuthoUserFunc> authoUserFuncs = authoUserFuncRepository.findAllByAuId(sysAuthoUser.getId());
                if(authoUserFuncs!=null && !authoUserFuncs.isEmpty()){
                    List<SysBaseFuncDTO> funcDTOS = authoUserFuncs.stream().map(sysAuthoUserFunc -> {
                        Optional<SysBaseFunc> funcOptional = funcRepository.findById(sysAuthoUserFunc.getFuncId());
                        if(funcOptional.isPresent()){
                            return funcMapper.toDTO(funcOptional.get());
                        }
                        return null;
                    }).collect(Collectors.toList());
                    authoMenuInfo.setFuncs(funcDTOS);
                }
                return authoMenuInfo;
            }).collect(Collectors.toList());
            return authoMenuInfos;
        }
        return null;
    }

    /**
     * 获取部门菜单权限
     * @param userId
     * @param proMark
     * @return
     */
    private List<AuthoMenuInfo> getGroupAuthoMenus(Long userId, String proMark) {
        List<SysBaseUg> ugList = ugRepository.findAllByUserIdAndDelIsFalse(userId);
        if (ugList != null && !ugList.isEmpty()) {
            List<AuthoMenuInfo> amInfos = new ArrayList<>();
            for (SysBaseUg ug : ugList) {
                List<SysAuthoGroup> authoGroupList = authoGroupRepository.findAllByGroupIdAndProMarkOrderById(ug.getGroupId(), proMark);
                if (authoGroupList != null && !authoGroupList.isEmpty()) {
                    List<AuthoMenuInfo> authoMenuInfos = authoGroupList.stream().map(sysAuthoUser -> {
                        Optional<SysBaseMenu> menuOptional = menuRepository.findById(sysAuthoUser.getMenuId());
                        AuthoMenuInfo authoMenuInfo = new AuthoMenuInfo();
                        if (menuOptional.isPresent()) {
                            SysBaseMenu menu = menuOptional.get();
                            authoMenuInfo.setMenuInfo(menuMapperExpand.toDTO(menu));
                        }
                        List<SysAuthoGroupFunc> authoUserFuncs = authoGroupFuncRepository.findAllByAgId(sysAuthoUser.getId());
                        if (authoUserFuncs != null && !authoUserFuncs.isEmpty()) {
                            List<SysBaseFuncDTO> funcDTOS = authoUserFuncs.stream().map(sysAuthoUserFunc -> {
                                Optional<SysBaseFunc> funcOptional = funcRepository.findById(sysAuthoUserFunc.getFuncId());
                                if(funcOptional.isPresent()){
                                    return funcMapper.toDTO(funcOptional.get());
                                }
                                return null;
                            }).collect(Collectors.toList());
                            authoMenuInfo.setFuncs(funcDTOS);
                        }
                        return authoMenuInfo;
                    }).collect(Collectors.toList());
                    amInfos.addAll(authoMenuInfos);
                }
            }
            return amInfos;
        }
        return null;
    }

    /**
     * 获取用户角色菜单权限
     * @param userId
     * @param proMark
     * @return
     */
    private List<AuthoMenuInfo> getRoleAuthoMenus(Long userId, String proMark) {
        List<SysBaseUr> urList = urRepository.findAllByUserIdAndDelIsFalse(userId);
        if (urList != null && !urList.isEmpty()) {
            List<AuthoMenuInfo> amInfos = new ArrayList<>();
            for (SysBaseUr ur : urList) {
                List<SysAuthoRole> authoRoleList = authoRoleRepository.findAllByGroupIdAndRoleIdAndProMarkOrderById(ur.getGroupId()
                        , ur.getRoleId(), proMark);
                if (authoRoleList != null && !authoRoleList.isEmpty()) {
                    List<AuthoMenuInfo> authoMenuInfos = authoRoleList.stream().map(sysAuthoRole -> {
                        Optional<SysBaseMenu> menuOptional = menuRepository.findById(sysAuthoRole.getMenuId());
                        AuthoMenuInfo authoMenuInfo = new AuthoMenuInfo();
                        if (menuOptional.isPresent()) {
                            SysBaseMenu menu = menuOptional.get();
                            authoMenuInfo.setMenuInfo(menuMapperExpand.toDTO(menu));
                        }
                        List<SysAuthoRoleFunc> authoUserFuncs = authoRoleFuncRepository.findAllByArId(sysAuthoRole.getId());
                        if (authoUserFuncs != null && !authoUserFuncs.isEmpty()) {
                            List<SysBaseFuncDTO> funcDTOS = authoUserFuncs.stream().map(sysAuthoUserFunc -> {
                                Optional<SysBaseFunc> funcOptional = funcRepository.findById(sysAuthoUserFunc.getFuncId());
                                if(funcOptional.isPresent()){
                                    return funcMapper.toDTO(funcOptional.get());
                                }
                                return null;
                            }).collect(Collectors.toList());
                            authoMenuInfo.setFuncs(funcDTOS);
                        }
                        return authoMenuInfo;
                    }).collect(Collectors.toList());
                    amInfos.addAll(authoMenuInfos);
                }
            }
            return amInfos;
        }
        return null;
    }

}
